package com.example.other.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.authority.common.entity.MyConst;
import com.example.authority.common.utils.RedisUtil;
import com.example.authority.common.utils.SecurityUtils;
import com.example.other.domain.*;
import com.example.other.domain.dto.OrdersDto;
import com.example.other.enums.OrderStates;
import com.example.other.mapper.*;
import com.example.other.service.OrdersService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
* @author Limhuang
* @description 针对表【orders】的数据库操作Service实现
* @createDate 2024-07-03 10:15:00
*/
@Service
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders>
    implements OrdersService{

    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private HospitalMapper hospitalMapper;
    @Autowired
    private SetmealMapper setmealMapper;

    @Autowired
    private SetmealdetailedMapper setmealdetailedMapper;

    @Autowired
    private CheckitemdetailedMapper checkitemdetailedMapper;

    @Autowired
    private  CidetailedreportMapper cidetailedreportMapper;

    @Autowired
    private CireportMapper cireportMapper;

    @Autowired
    private RedisUtil redisUtil;

    // 清除订单缓存
    private void clearOrderCache(){
        redisUtil.expire(MyConst.ORDER_KEY, 0);
    }

    @Override
    public Orders createOrder(Date date, Integer hpid, Integer smid) {

        clearOrderCache();

        // 获取当前用户
        String userid = SecurityUtils.getCurrentUser().getUser().getId().toString();
        Orders orders = new Orders();
        orders.setOrderdate(date);
        orders.setUserid(userid);
        orders.setHpid(hpid);
        orders.setSmid(smid);
        orders.setState(OrderStates.ORDERED.getCode());

        // 检验是否已存在相同订单
        if (ordersMapper.selectList(new QueryWrapper<Orders>().allEq(Map.of(
                "orderDate", date,
                "userId", userid,
                "hpId", hpid,
                "smId", smid,
                "state",OrderStates.ORDERED.getCode()
        ))).size()>0) {
            throw new RuntimeException("该预约已存在");
        }
        ordersMapper.insert(orders);
        // all meal's check item details
        List<Setmealdetailed> setmealdetailedList = setmealdetailedMapper.selectList(new QueryWrapper<Setmealdetailed>().eq("smId", smid));
        List<Integer> checkitemdetailedIds = new ArrayList<>();
        setmealdetailedList.forEach(setmealdetailed -> {
            checkitemdetailedIds.add(setmealdetailed.getCiid());
        });
        QueryWrapper<Checkitemdetailed> checkitemdetailedQueryWrapper = new QueryWrapper<>();
        checkitemdetailedQueryWrapper.lambda().in(Checkitemdetailed::getCiid, checkitemdetailedIds);
        List<Checkitemdetailed> checkitemdetailedList = checkitemdetailedMapper.selectList(checkitemdetailedQueryWrapper);

        //define a list to store row to insert into cidetailedreport,cireport

        List<Cidetailedreport> cidetailedreportList = new ArrayList<>();
        List<Cireport> cireportList = new ArrayList<>();

        int size=checkitemdetailedList.size();
        for(int i=0;i<size;i++){
            Cidetailedreport cidetailedreport = new Cidetailedreport();
            Cireport cireport = new Cireport();
            Checkitemdetailed checkitemdetailed = checkitemdetailedList.get(i);
            cidetailedreport.setCiid(checkitemdetailed.getCiid());
            cidetailedreport.setName(checkitemdetailed.getName());
            cidetailedreport.setUnit(checkitemdetailed.getUnit());
            cidetailedreport.setMinrange(checkitemdetailed.getMinrange());
            cidetailedreport.setMaxrange(checkitemdetailed.getMaxrange());
            cidetailedreport.setNormalvalue(checkitemdetailed.getNormalvalue());
            cidetailedreport.setNormalvaluestring(checkitemdetailed.getNormalvaluestring());
            cidetailedreport.setType(checkitemdetailed.getType());
            cidetailedreport.setOrderid(orders.getOrderid());

            cireport.setCiid(checkitemdetailed.getCiid());
            cireport.setCiname(checkitemdetailed.getName());
            cireport.setOrderid(orders.getOrderid());

            cidetailedreportMapper.insert(cidetailedreport);
            cireportMapper.insert(cireport);

            cidetailedreportList.add(cidetailedreport);
            cireportList.add(cireport);
        }



        return orders;
    }

    /**
     * 取消订单。
     * 通过订单ID查询订单信息，将订单状态更新为已取消，并返回更新后的订单信息。
     *
     * @param id 订单ID，用于唯一标识一个订单。
     * @return 返回更新后的订单信息。
     */
    @Override
    public Orders cancelOrder(String id) {

        clearOrderCache();

        // 根据订单ID查询订单
        Orders orders = ordersMapper.selectById(id);

        Instant orderTime = orders.getOrderdate().toInstant();
        Instant now = Instant.now();
        Duration duration = Duration.between(orderTime, now);
        if (Math.abs(duration.toHours()) <= 24) {
            throw new RuntimeException("预约在24小时内，无法取消");
        }

        // 将订单状态设置为已取消/已退款
        if(orders.getState()==OrderStates.ORDERED.getCode()){
            orders.setState(OrderStates.CANCELLED.getCode());
        }else if(orders.getState()==OrderStates.PAID.getCode()){
            orders.setState(OrderStates.REFUNDED.getCode());
        }

        // 更新订单状态到数据库
        ordersMapper.updateById(orders);
        // 返回更新后的订单信息
        return orders;
    }

    /**
     * 查询用户订单列表。
     * 该方法通过查询数据库获取当前用户的所有订单，并将订单数据转换为订单DTO（数据传输对象）的形式返回。
     * 在转换过程中，还会额外查询每个订单对应的医院和套餐信息，以丰富订单数据的内容。
     * 最后，对订单DTO列表按照订单日期进行降序排序，确保最新的订单出现在列表前面。
     *
     * @return 返回包含所有订单信息的订单DTO列表。
     */
    @Override
    public List<OrdersDto> listOrder() {
        // 根据当前用户ID查询订单列表
        List<Orders> list = ordersMapper.selectList(new QueryWrapper<Orders>().eq(
                "userId", SecurityUtils.getCurrentUser().getUser().getId().toString()).orderByDesc("orderDate"));

        List<OrdersDto> dtoList = new ArrayList<>();
        // 遍历订单列表，将每个订单转换为订单DTO，并查询对应的医院和套餐信息
        list.forEach(orders -> {
            OrdersDto ordersDto = new OrdersDto();
            BeanUtils.copyProperties(orders, ordersDto);
            ordersDto.setHospital(hospitalMapper.selectOne(
                    new QueryWrapper<Hospital>().eq("hp_Id", orders.getHpid())));
            ordersDto.setSetmeal(setmealMapper.selectOne(
                    new QueryWrapper<Setmeal>().eq("smId", orders.getSmid())));
            dtoList.add(ordersDto);
        });

        // 对订单DTO列表按照订单日期进行降序排序
        // 按照时间排序
        dtoList.sort((o1, o2) -> o2.getOrderdate().compareTo(o1.getOrderdate()));
        return dtoList;
    }

}




